#include "EndDestSendHandlerBase.h"

using namespace std;
using namespace log4cplus;

Logger EndDestSendHandlerBase::log=GetLogger(LOG4CPLUS_TEXT("EndDestSendHandlerBase"));

ITransHandler::ExecuteResultCode EndDestSendHandlerBase::Execute(ClientContext &client,OVERLAPPED *ovl)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	SOCKET sock;
	WSABUF *buffer;
	WSABUF *weakRefBuffer;
	OVERLAPPED *recvSendOvl;
	string *fullBuffer;
	GetRecvSendInfo(client,&sock,&buffer,&weakRefBuffer,&recvSendOvl,&fullBuffer);

	DWORD sendCount;
	DWORD flags;
	BOOL result=::WSAGetOverlappedResult(sock,recvSendOvl,&sendCount,true,&flags);
	int errCode=::WSAGetLastError();
	if(result)
	{
		if(sendCount<weakRefBuffer->len)
		{
			weakRefBuffer->buf+=sendCount;
			weakRefBuffer->len-=sendCount;
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send request data not complete,sended count:%d,left count:%d."),clienSequenceNo,sendCount,
				weakRefBuffer->len);
			::ZeroMemory(recvSendOvl,sizeof(OVERLAPPED));
			int result=::WSASend(sock,weakRefBuffer,1,NULL,0,recvSendOvl,NULL);
			int errCode=::WSAGetLastError();
			if(result!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Send data failed,error code:%d."),clienSequenceNo,errCode);
				return OnExecuteError(client,recvSendOvl,ITransHandler::ExecuteFatalError);
			}
		}
		else if(GetPartialTransIndex(client)!=0&&GetPartialTransIndex(client)<fullBuffer->size())
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Continue to send server request data(big data)."),clienSequenceNo);
			const char *srcIndex=fullBuffer->c_str()+GetPartialTransIndex(client);
			std::string::size_type leftSize=fullBuffer->size()-GetPartialTransIndex(client);
			if(leftSize>buffer->len)
			{
				memcpy_s(buffer->buf,buffer->len,srcIndex,buffer->len);
				SetPartialTransIndex(client,GetPartialTransIndex(client)+buffer->len);
				weakRefBuffer->len=buffer->len;
			}
			else
			{
				memcpy_s(buffer->buf,buffer->len,srcIndex,leftSize);
				SetPartialTransIndex(client,fullBuffer->size());
				weakRefBuffer->len=leftSize;
			}
			weakRefBuffer->buf=buffer->buf;

			::ZeroMemory(recvSendOvl,sizeof(OVERLAPPED));
			int sendResult=::WSASend(sock,weakRefBuffer,1,NULL,0,recvSendOvl,NULL);
			int errCode=::WSAGetLastError();
			if(sendResult!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Continue to send server request data(big data) failed,error code:%d."),
					clienSequenceNo,errCode);
				return OnExecuteError(client,recvSendOvl,ITransHandler::ExecuteFatalError);
			}
		}
		else
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Server request data send finished,last send %d bytes,start to receive first original server data."),
				clienSequenceNo,sendCount);
			RequestFullSendPostProcess(client);
			delete client.SetCurrentHandler(GetNextHandler());
			::ZeroMemory(recvSendOvl,sizeof(OVERLAPPED));
			result=::WSARecv(sock,buffer,1,NULL,&flags,recvSendOvl,NULL);
			errCode=::WSAGetLastError();
			if(result!=0&&errCode!=WSA_IO_PENDING)
			{
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Begin receive first server data failed,error code:%d."),clienSequenceNo,errCode);
				return OnExecuteError(client,ovl,ITransHandler::ExecuteFatalError);
			}
		}
	}
	else
	{
		LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Get send request data's result failed,error code:%d."),clienSequenceNo,errCode);
		return OnExecuteError(client,ovl,ITransHandler::ExecuteFatalError);
	}
	return ITransHandler::ExecuteOK;
}